package com.bailiban.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bailiban.entity.*;
import com.bailiban.repository.*;
import com.bailiban.service.Cov19Service;
import com.bailiban.utils.HttpUtil;
import com.bailiban.utils.Result;
import com.bailiban.utils.ResultCode;
import jdk.nashorn.internal.runtime.arrays.IteratorAction;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author zhulang
 * @Classname Cov19ServiceImpl
 * @Description TODO
 * @Date 2020/3/18 23:40
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class Cov19ServiceImpl implements Cov19Service {
    private final String URL = "http://sa.sogou.com/new-weball/page/sgs/epidemic";
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private ProvinceCovRepository provinceCovRepository;
    @Autowired
    private HistoryDataRepository historyDataRepository;
    @Autowired
    private CityCovRepository cityCovRepository;
    @Autowired
    private YesterdayIncreasedRepository yesterdayIncreasedRepository;
    @Autowired
    private OverseaRepository overseaRepository;
    @Autowired
    private NewsRepository newsRepository;
    @Override
    public Result updateCovData(String date) {
//        先从redis中获取日期标记，如果有对应的日期，就直接从redis中获取数据，没有就爬取数据
        String covDate;
        try {
            covDate = redisTemplate.boundValueOps("covDate").get();
        } catch (Exception e) {
            return Result.failure(ResultCode.REDIS__CONNECTION_ERROR);
        }
        JSONObject jsonObject;
//       如果redis日期不存在，或者不等于当天的日期
        if (StringUtils.isEmpty(covDate) || !date.equals(covDate)) {
//            爬取数据
            String resultData = HttpUtil.getResultData(URL, null);
            if ("error".equals(resultData)) {
                //抓取数据失败，受限制了
                return Result.failure(ResultCode.COV2019_DATA_GET_FORBIDDEN);
            } else {
                //抓取数据成功
                jsonObject = handleData(resultData);
//               将爬取的数据全部 存入redis中
                redisTemplate.boundValueOps("covDatas").set(jsonObject.toString());
//                将日期标志存入redis中
                redisTemplate.boundValueOps("covDate").set(date);
            }

        } else {
            return Result.failure(ResultCode.COV2019_DATA_IS_EXISTED);
        }
        try {
//        存储省的数据
            saveProvinceData(jsonObject);
//        存储市的数据
            saveCityData(jsonObject);
//        存储昨日新增数据
            saveYesterDayData(jsonObject);
//        存储历史记录
            saveHistoryData();
//        存储外海疫情数据
            saveOversea(jsonObject);
//            存储新闻
            saveNews(jsonObject);
        } catch (Exception e) {
            return Result.failure(ResultCode.UNKNOWN_REASON);
        }
        return Result.success(jsonObject);
    }

    private Result saveNews(JSONObject jsonObject) {
        //    获取json里面的data
        JSONObject data = jsonObject.getJSONObject("data");
        //    获取data里面的新闻数据
        JSONObject timeline = data.getJSONObject("timeline");

        JSONArray list = timeline.getJSONArray("list");
        List<News> newsList = JSON.parseArray(list.toString(), News.class);
        newsRepository.saveAll(newsList);
        return Result.success();
    }

    private Result saveOversea(JSONObject jsonObject) {
        //    获取json里面的data
        JSONObject data = jsonObject.getJSONObject("data");
//    获取data里面的区域数据
        JSONArray overseas = data.getJSONArray("overseas");
        List<Oversea> newList = JSON.parseArray(overseas.toString().replaceAll("\"confirmedIncr\":\"-\"", "\"confirmedIncr\":0"), Oversea.class);
//        先查询数据库
        List<Oversea> oldList = overseaRepository.findAll();
        for (Oversea oversea : newList) {
            if(!StringUtils.isEmpty(overseas)){
                oldList.stream().filter(overseaOld->overseaOld.getCountryFullName().equals(oversea.getCountryFullName()))
                        .findAny().ifPresent(overseaOld->oversea.setOid(overseaOld.getOid()));
            }
        }
        Oversea china = new Oversea();
        JSONObject domesticStats = data.getJSONObject("domesticStats");
        Long timestamp =(Long) domesticStats.get("timestamp");
        Date createDate = new Date(timestamp);
        Integer diagnosed = (Integer) domesticStats.get("diagnosed");
        Integer suspect = (Integer) domesticStats.get("suspect");
        Integer death = (Integer) domesticStats.get("death");
        Integer cured = (Integer) domesticStats.get("cured");
        Integer currentConfirmedCount = (Integer) domesticStats.get("currentConfirmedCount");
        china.setOid(191);
        china.setCountryFullName("China");
        china.setCountryShortCode("CHN");
        china.setCreateTime(createDate);
        china.setCuredCount(cured);
        china.setCurrentConfirmedCount(currentConfirmedCount);
        china.setDeadCount(death);
        china.setLocationId(0);
        china.setSuspectedCount(suspect);
        china.setContinents("亚洲");
        china.setProvinceName("中国");
        china.setConfirmedCount(diagnosed);
        newList.add(china);
        overseaRepository.saveAll(newList);
        return Result.success();
    }

    public JSONObject handleData(String str) {
        //    对数据进行处理
        String[] split = str.split("window.__INITIAL_STATE__ =");
//    分割的数据部分
        String splitData = split[1];
//    截取的有效数据
        String substring = splitData.substring(0, splitData.indexOf("</script>"));
//    System.out.println(substring);
//将有效数据的格式进行转换，json-->jsonObject对象
        JSONObject jsonObject = JSON.parseObject(substring);
        return jsonObject;
    }

    //    存储省份数据
    public Result saveProvinceData(JSONObject jsonObject) {
        JSONObject data = jsonObject.getJSONObject("data");
//        获取json数据中的省份数据-->area
        JSONArray area = data.getJSONArray("area");
        List<ProvinceCov> provinceCovList = JSON.parseArray(area.toString(), ProvinceCov.class);
//        查询数据库，目的是为了获取每个省唯一的id
        List<ProvinceCov> oldCovList = provinceCovRepository.findAll();
//        存储到数据库中
        for (ProvinceCov provinceCov : provinceCovList) {

//                需要判断数据库中是否有数据，即oldCovList是否为空
            if (!StringUtils.isEmpty(oldCovList)) {
                //数据库有数据
                //通过location_id进行省份的匹配
//                    通过jdk8新特性stream
                oldCovList.stream().filter(provinceCov1 -> provinceCov1.getLocationId().equals(provinceCov.getLocationId())).findAny().ifPresent(
                        provinceCov1 -> {
//                                //给新爬取的对象赋予id
                            provinceCov.setProvinceId(provinceCov1.getProvinceId());

                        }
                );
            }
            provinceCov.setDate(new Date());
        }

        provinceCovRepository.saveAll(provinceCovList);
        return Result.success();
    }

    /**
     * 保存记录
     */
    public Result saveHistoryData() {
        List<ProvinceCov> nCovList;
        nCovList = provinceCovRepository.findAll();
        //存入记录
        List<HistoryData> historyDataList = new ArrayList<>();
        for (ProvinceCov ProvinceCov : nCovList) {
            HistoryData historyData = new HistoryData();
            BeanUtils.copyProperties(ProvinceCov, historyData);
            historyData.setDate(new Date());
            historyData.setProvinceCov(ProvinceCov);
            historyDataList.add(historyData);
        }
        historyDataRepository.saveAll(historyDataList);
        return Result.success();
    }

    /**
     * 保存市数据
     */
    public Result saveCityData(JSONObject jsonObj) {
        //得到 data对应JSON对象格式的总信息
        JSONObject data = jsonObj.getJSONObject("data");
        JSONArray area = data.getJSONArray("area");
        Object[] objects = area.toArray();
        //要循环start
        for (int i = 0; i < objects.length; i++) {
            Object object = objects[i];
//            获取每个省份对象
            JSONObject object1 = (JSONObject) object;
//            获取每个省的唯一邮政编码locationId
            Integer locationId = object1.getInteger("locationId");
            //            要找到省份的id作为外键
            ProvinceCov provinceCovT = provinceCovRepository.findByLocationId(locationId);
            JSONArray cities = object1.getJSONArray("cities");
            List<CityCov> cityCovs =
                    JSON.parseArray(cities.toString(), CityCov.class);
            List<CityCov> all = cityCovRepository.findAll();
            for (CityCov cityCov : cityCovs) {
//                赋予外键
                cityCov.setProvinceCov(provinceCovT);
                all.stream()
                        .filter(cityCov1 -> cityCov1.getCityName().equals(cityCov.getCityName()))
                        .findAny()
                        .ifPresent(cityCov1 -> cityCov.setCityId(cityCov1.getCityId()));
                cityCov.setDate(new Date());
            }
            cityCovRepository.saveAll(cityCovs);
        }
//            循环结束end
        return Result.success();
    }

    /**
     * 保存昨日新增数据
     */
    public Result saveYesterDayData(JSONObject jsonObj) throws ParseException {
        JSONObject data = jsonObj.getJSONObject("data");
        JSONArray area = data.getJSONArray("area");

        Object[] objects = area.toArray();
        //要循环start
        for (int i = 0; i < objects.length; i++) {
            Object object = objects[i];
            JSONObject object1 = (JSONObject) object;
            Integer locationId = object1.getInteger("locationId");
            //            要找到省份的id作为外键
            ProvinceCov provinceCovT;
            provinceCovT = provinceCovRepository.findByLocationId(locationId);
            JSONObject yesterdayIncreasedJson = object1.getJSONObject("yesterdayIncreased");
            YesterdayIncreased yesterdayIncreased = JSONObject.toJavaObject(yesterdayIncreasedJson, YesterdayIncreased.class);
//           获取昨天日期
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.HOUR_OF_DAY, -24);
            String yesterdayDate = dateFormat.format(calendar.getTime());
            Date yesterday = dateFormat.parse(yesterdayDate);
            System.out.println(yesterday);
            yesterdayIncreased.setDate(yesterday);
            yesterdayIncreased.setProvinceCov(provinceCovT);
            yesterdayIncreasedRepository.save(yesterdayIncreased);
        }
        //            循环结束end
        return Result.success();
    }
}
